#pragma once
/**
 * 这是一个封装了sqlite3接口的一个封装类，旨在更简易的在C++代码中使用sqlite3的接口
 *      封装的接口：
 *          1. 创建/打开文件
 *          2. sql查询（增删查改）
 *          3.关闭句柄文件
 */

#include <iostream>
#include <string>
#include <vector>
#include "sqlite3.h"

namespace NS_SQLiteHepler
{
    using SQLCallback = int(void *, int, char **, char **);
    class SQLite3Helper
    {
    public:
        SQLite3Helper(const std::string &file_path_name) : _file_path_name(file_path_name), _handler(nullptr)
        {
        }

        bool open(int security_level = SQLITE_OPEN_FULLMUTEX)
        {
            int ret = sqlite3_open_v2(_file_path_name.c_str(), &_handler, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | security_level, nullptr);
            if (ret != SQLITE_OK)
            {
                std::cout << "打开或创建文件 " << _file_path_name << " 失败" << std::endl
                          << "，原因：" << sqlite3_errmsg(_handler) << std::endl;
                return false;
            }
            return true;
        }

        // 增
        bool insert(const std::string &sql)
        {
            return execute(sql);
        }

        // 删
        bool erase(const std::string &sql)
        {
            return execute(sql);
        }

        // 改
        bool update(const std::string sql)
        {
            return execute(sql);
        }

        // 查
        template <class T>
        bool select(const std::string sql, SQLCallback cb, T& container)
        {
            return execute(sql, cb, &container);
        }

        ~SQLite3Helper()
        {
            sqlite3_close_v2(_handler);
        }

    private:
        bool execute(const std::string sql, SQLCallback cb = nullptr, void *arg = nullptr, char **err = nullptr)
        {
            int ret = sqlite3_exec(_handler, sql.c_str(), cb, arg, err);
            if (ret != SQLITE_OK)
            {
                std::cout << "SQL语句：" << sql << std::endl
                          << "，原因：" << sqlite3_errmsg(_handler) << std::endl;
                return false;
            }

            return true;
        }

    private:
        // SQLite数据库中不存在关于库的操作，只有表的操作，并且SQLite中一个库就是一个单独的文件
        std::string _file_path_name;
        // 使用SQLite进行持久化数据写入到磁盘，所依托的都是一个句柄
        sqlite3 *_handler;
    };
}